home *** CD-ROM | disk | FTP | other *** search
- ;*************************************************************************
- ;** mmu.library **
- ;** **
- ;** a system library for arbitration and control of the MC68K MMUs **
- ;** **
- ;** © 1998 THOR-Software, Thomas Richter **
- ;** No commercial use, reassembly, modification without prior, written **
- ;** permission of the authors. **
- ;** Including this library in any commercial software REQUIRES a **
- ;** written permission and the payment of a small fee. **
- ;** **
- ;** This is an internal header file, do not depend on anything here. **
- ;** Use the official include files. **
- ;** Distributed only for the mmu.library development group for private **
- ;** use. **
- ;** **
- ;**---------------------------------------------------------------------**
- ;** Block: Memory pool operations **
- ;** Because the exec memory pool functions are bugged and it is not **
- ;** clear whether SetPatch is installed to fix it, we use our own. **
- ;*************************************************************************
-
- ;FOLD Include
- include INC:macros.asm
- include inc:exec_lib.asm
- include mu_lib.i
- include mu_alerts.i
- include mu_context.i
- ;ENDFOLD
- ;FOLD External references
- xref MMUName
- xref AllocAligned
- ;ENDFOLD
-
- section main_code,code
-
- machine mc68020
-
- ;FOLD MUCreatePool
- ;*************************************************
- ;** MUCreatePool **
- ;** d0=ReqMents,d1=puddleSize,d2=puddleThresh **
- ;*************************************************
- xdef MUCreatePool
- MUCreatePool:
- saveregs a6
-
- move.l mulib_SysBase(a6),a6
-
- sub.l a0,a0
- cmp.l d2,d1
- bcs.s .failexit ;puddlesize must be larger
- move.l d0,-(sp)
- moveq #7,d0
- add.l d0,d1
- not.b d0
- and.b d0,d1 ;round puddleSize
- move.l d1,-(sp)
- moveq #1,d1 ;public memory
- moveq #$18,d0
- jsr AllocMem(a6) ;AllocMem
- move.l (sp)+,d1 ;puddleSize
- move.l (sp)+,a0 ;ReqMents
- tst.l d0
- beq.s .failexitd0
- exg.l d0,a0 ;ReqMents->d0,Ptr->a0
- move.l a0,8(a0)
- addq.l #4,a0
- clr.l (a0)
- move.l a0,-(a0) ;NewList
- movem.l d0-d2,$c(a0)
- .failexit:
- move.l a0,d0
- .failexitd0:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD MUDeletePool
- ;*************************************************
- ;** MUDeletePool **
- ;** delete the pool *a0 **
- ;*************************************************
- xdef MUDeletePool
- MUDeletePool:
- saveregs a2/a6
-
- move.l mulib_SysBase(a6),a6
-
- move.l a0,d0
- beq.s .nopoolexit
- move.l (a0),a2 ;get first
- do
- move.l (a2),d2 ;next entry?
- break.s eq
- move.l a2,a1 ;if so, take it
- move.l d2,a2 ;remember next
- jsr FreeVec(a6) ;release it
- loop.s
- lea -4(a2),a1 ;get pointer to head
- moveq #$18,d0
- jsr FreeMem(a6) ;release head
- .nopoolexit:
-
- loadregs
- rts
- ;ENDFOLD
- ;FOLD MUAllocPooled
- ;*************************************************
- ;** MUAllocPooled **
- ;** d0=MemSize **
- ;** a0=PoolHeader **
- ;** d1=ReqMents **
- ;*************************************************
- xdef MUAllocPooled
- MUAllocPooled:
- saveregs d2-d4/a2-a3/a6
-
- move.l mulib_SysBase(a6),a6
-
- move.l d1,d4 ;keep ReqMents
- move.l d0,d2 ;ByteSize->d2
- beq .exit
- move.l a0,d0 ;Header available ?
- beq .exit
- move.l a0,a2 ;keep it
-
- cmp.l $14(a2),d2 ;compare with puddlesthres
- bhs.s .allocdirect ;too big, get directly
- cmp.b 3+$c(a2),d4 ;right type ?
- bne.s .allocdirect ;no, so get directly
- ;allocate pool
- .tryagain:
- move.l (a2),d3 ;*first node
- do
- move.l d3,a3
- move.l (a3),d3 ;available ?
- beq.s .addpool ;no, so add new pool
- tst.l 8(a3) ;is this a private memory piece ?
- beq.s .addpool ;no, so allocate new
-
- move.l a3,a0
- move.l d2,d0 ;size to d0
- addq.l #4,d0
- jsr Allocate(a6) ;allocate private
- tst.l d0
- while.s eq ;if not, try next
- move.l d0,a0 ;*Mem->a0
- addq.l #4,d2 ;one additional long
- ;clear it ?
- btst #$10,d4
- beq.s .noclear
- move.l a0,a1
- move.l d2,d1 ;size -> d1
- addq.l #7,d1
- lsr.l #3,d1
- subq.l #1,d1 ;size in double long words
- move.w d1,d0
- swap d1
- moveq #0,d3
- .swp1: move.l d3,(a1)+
- move.l d3,(a1)+
- dbra d0,.swp1
- dbra d1,.swp1
- .noclear:
- move.l d2,(a0)+ ;enter length
- move.l a0,d0
- bra .exit
- .allocdirect:
- move.l d2,d0 ;size -> d0
- addq.l #8,d0
- addq.l #4,d0 ;+$c
- move.l d4,d1 ;get length
- jsr AllocVec(a6) ;get as vector
- tst.l d0
- beq .exit ;exit if no memory
- move.l d0,a1 ;*Mem->a1
- move.l a2,a0 ;Liste->a0
- addq.l #4,a0
- move.l 4(a0),d0
- move.l a1,4(a0)
- exg.l d0,a0
- movem.l d0/a0,(a1)
- move.l a1,(a0) ;AddTail
- addq.l #8,a1 ;length of the node structure
- clr.l (a1)+ ;erase it. Private, no pool
- move.l a1,d0 ;return pointer
- bra.s .exit
- .addpool: ;add a new pool here
- move.l $10(a2),d0 ;PuddleSize->d0
- moveq #$24,d1
- add.l d1,d0 ;+Headersize
- move.l $c(a2),d1 ;ReqMents
- jsr AllocVec(a6)
- tst.l d0
- beq.s .exit ;exit if no memory
-
- move.l d0,a3 ;head->a3
- move.l d0,a1
- move.l a2,a0
-
- move.l (a0),d0
- move.l a1,(a0)
- movem.l d0/a0,(a1)
- move.l d0,a0
- move.l a1,4(a0) ;AddHead
-
- moveq #$a,d0
- move.b d0,8(a3) ;Type,Pri: auf jeden Fall nicht 0
- move.b d0,9(a3)
- move.l #MMUName,$a(a3) ;set name: mmu.library
- move.l $c(a2),d1 ;ReqMents
- move.l d1,$e(a3) ;save as reqments of the pool
- lea $24(a3),a0 ;start of the memory list
- moveq #~7,d1
- move.l a0,d0 ;address ->a0
- and.l d0,d1 ;divisible by 8
- move.l d1,a0
- move.l $10(a2),d0 ;PuddleSize->d0
- move.l a0,$10(a3) ;*First
- move.l a0,$14(a3) ;*Lower
- move.l d0,$1c(a3) ;Free
- clr.l (a0) ;clear *NextHunk
- move.l d0,4(a0) ;length
- add.l d0,a0 ;end
- move.l a0,$18(a3) ;*High
- bra .tryagain
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD MUFreePooled
- ;*************************************************
- ;** MUFreePooled **
- ;** memory *a1, pool *a0 **
- ;*************************************************
- xdef MUFreePooled
- MUFreePooled:
- saveregs a2-a3/a6
-
- move.l a1,d1 ;no memory, freepooled
- beq .exit
-
- move.l mulib_SysBase(a6),a6
-
- move.l a0,d1
- beq .alert ;no pool -> alert
-
- lea -$c(a1),a2 ;pointer to begin
-
- ;get the responsible header
- move.l (a0),d1 ;*First
- do
- move.l d1,a3
- move.l (a3),d1 ;*next
- beq.s .alert ;not found -> alert
- cmp.l a2,a3 ;our block ?
- beq.s .freeprivate
- tst.l 8(a3) ;do we have a private one ?
- reloop.s eq
- cmp.l $14(a3),a1 ;compare with lower
- reloop.s lo ;continue if too small
- cmp.l $18(a3),a1
- while.s hs ;or too large
-
- move.l a3,a0
- move.l -(a1),d0 ;get length
- jsr Deallocate(a6) ;release
-
- move.l 4(a3),a1 ;*Pred
- move.l 4(a1),d1 ;exists ?
- beq.s .nopred
- move.l d1,a0 ;PredPred->a0
- move.l a3,(a0) ;insert me as predicessor of predpred
- move.l a0,4(a3) ;my pred is predpred
- move.l a3,4(a1) ;I'm pred of my old pred
- move.l (a3),a0 ;get succ
- move.l a0,(a1) ;this is succ of my old succ
- move.l a1,4(a0) ;pred is pred of my succ
- move.l a1,(a3) ;that's my succ
- ;or, in other words, move this
- ;node towards the head of the list
- .nopred:
- move.l a3,a2 ;*head -> a2
-
- move.l $1c(a2),d0 ;get free mem
- add.l $14(a2),d0 ;plus lower
- cmp.l $18(a2),d0 ;-Upper =0 -> this block is FREE
- bne.s .exit
- .freeprivate: ;release a complete pool
- move.l a2,a1 ;to a1
- move.l a1,d0
- move.l (a1)+,a0 ;next->a0
- move.l (a1),a1 ;pred->a1
- move.l a0,(a1)
- move.l a1,4(a0) ;remove
- move.l a2,a1
- jsr FreeVec(a6) ;and release
- bra.s .exit
- .alert:
- saveregs a5/d7
- move.l #AN_BadFreePool,d7
- sub.l a5,a5
- jsr Alert(a6) ;and alert
- loadregs
- .exit:
- moveq #0,d0
- loadregs
- rts
- ;ENDFOLD
-
- ;FOLD AllocContextMem
- ;*************************************************
- ;** AllocContextMem **
- ;** allocate from the context pool d0 bytes **
- ;*************************************************
- xdef AllocContextMem
- AllocContextMem:
- move.l a6,a1
- move.l mulib_SysBase(a6),a6
- lea mulib_PoolSemaphore(a1),a0
- jsr ObtainSemaphore(a6) ;does not alter registers
-
- move.l a1,a6
- move.l #$10001,d1 ;Clear it
- move.l mulib_ContextPool(a6),a0
- bsr MUAllocPooled
-
- move.l a6,a1
- move.l mulib_SysBase(a6),a6
- lea mulib_PoolSemaphore(a1),a0
- jsr ReleaseSemaphore(a6)
-
- move.l a1,a6
- tst.l d0
- rts
- ;ENDFOLD
- ;FOLD FreeContextMem
- ;*************************************************
- ;** FreeContextMem **
- ;** release the allocated memory at *a1 **
- ;** size is implicit **
- ;*************************************************
- xdef FreeContextMem
- FreeContextMem:
- move.l a1,d0
- move.l a6,a1
- move.l mulib_SysBase(a6),a6
- lea mulib_PoolSemaphore(a1),a0
- jsr ObtainSemaphore(a6) ;does not alter registers
-
- move.l a1,a6
- move.l mulib_ContextPool(a6),a0
- move.l d0,a1
- bsr MUFreePooled
-
- move.l a6,a1
- move.l mulib_SysBase(a6),a6
- lea mulib_PoolSemaphore(a1),a0
- jsr ReleaseSemaphore(a6)
-
- move.l a1,a6
- rts
- ;ENDFOLD
-
- ;FOLD AllocPointerTable
- ;*************************************************
- ;** AllocPointerTable **
- ;** allocate a pointer table for the level d0 **
- ;** of the MMU table **
- ;** *a5=Context **
- ;** **
- ;**---------------------------------------------**
- ;** this is currently a stupid stubs for **
- ;** AllocAbs. A future version should handle a **
- ;** pool with cache-inhibited memory **
- ;*************************************************
- xdef AllocPointerTable
- AllocPointerTable:
- tst.b mulib_MMUType(a6) ;no MMU, no table
- beq.s .failexit
-
- move.b ctx_LevelATableSz(a5,d0.w*4),d1 ;#of bits
- move.l ctx_LevelAAlign(a5,d0.w*4),a0 ;get required alignment
- lsl.l #3,d1 ;plus the table again for the user data
-
- move.l d1,d0
- moveq #1,d1 ;memory type does not care
- bsr AllocAligned
- tst.l d0
- rts
- .failexit:
- moveq #0,d0
- rts
- ;ENDFOLD
- ;FOLD FreePointerTable
- ;*************************************************
- ;** FreePointerTable **
- ;** free a pointer table for the level d0 **
- ;** at *a1 **
- ;*************************************************
- xdef FreePointerTable
- FreePointerTable:
- move.l a1,d1
- beq.s .exit ;ignore silently
-
- move.l ctx_LevelATableSz(a5,d0.w*4),d0
-
- saveregs a6
-
- movem.l mulib_SysBase(a6),a6
- lsl.l #3,d0
- jsr FreeMem(a6)
-
- loadregs
- .exit:
- rts
- ;ENDFOLD
-
-